
#ifndef _NBODY_CUDA_BINDINGS_ADVANCED_
#define _NBODY_CUDA_BINDINGS_ADVANCED_

#include <ttg_ext/cuda_bindings.h>
#include "../Common/InterleavedBodies.h"
#include "PairedBodies.h"

using namespace ttg_ext::bindings;

class cudaBodyInteractor1 :public cudaBinding<InterleavedBodies::SubVector,
											  InterleavedBodies::SubVector>
{
	private:
		//Interacts bodies of required range.
		void interactRange(InterleavedBodies *bodies, size_t lo, size_t hi);
	public:
		virtual void process(InterleavedBodies::SubVector data)
		{
			try
			{
				interactRange(data.getOwner(),
							  data.getRealIndex(0),
							  data.getRealIndex(data.getSize()));
				sendNext(data);
			}
			catch (ttg::Error &err)
			{
				printf("CUDA Error: %s\n", err.toString());
			}
		}
};

class cudaBodyInteractor2 :public cudaBinding<PairedBodies, PairedBodies>
{
	private:
		//Interactc each body of the first range with each body of the second range.
		void interactRanges(InterleavedBodies *b1, size_t lo1, size_t hi1,
							InterleavedBodies *b2, size_t lo2, size_t hi2);
	public:
		virtual void process(PairedBodies data)
		{
			try
			{
				interactRanges(data.first.getOwner(),
							   data.first.getRealIndex(0),
							   data.first.getRealIndex(data.first.getSize()),
							   data.second.getOwner(),
							   data.second.getRealIndex(0),
							   data.second.getRealIndex(data.second.getSize()));
				sendNext(data);
			}
			catch (ttg::Error &err)
			{
				printf("CUDA Error: %s\n", err.toString());
			}
		}
};

#endif
